package org.jeecg.modules.gis.typeHandler.mysql;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.MultiLineString;
import org.locationtech.jts.io.WKBWriter;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;

import java.io.ByteArrayInputStream;
import java.sql.*;

/**
 * MyBatis TypeHandler 适配 MySQL Geometry 存储格式（带SRID）
 * 对 MultiLineString 类型做读写转换
 */
public class MysqlGeoMultiLineStringTypeHandler extends BaseTypeHandler<MultiLineString> {

    /**
     * 写入数据库时，将 MultiLineString 转为 WKB，MySQL geometry 字段可识别的二进制流
     * 注意：MySQL 会自动添加SRID
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, MultiLineString parameter, JdbcType jdbcType)
            throws SQLException {
        if (parameter != null) {
            // WKBWriter，输出二维坐标，1代表Little Endian格式（MySQL默认）
            WKBWriter writer = new WKBWriter(2, 1);
            byte[] wkb = writer.write(parameter);
            ByteArrayInputStream bais = new ByteArrayInputStream(wkb);
            ps.setBinaryStream(i, bais, wkb.length);
        } else {
            ps.setNull(i, Types.BINARY);
        }
    }

    /**
     * 读取数据库时，从二进制流中读取，跳过前4字节SRID，再用WKBReader解析成MultiLineString
     */
    @Override
    public MultiLineString getNullableResult(ResultSet rs, String columnName) throws SQLException {
        byte[] bytes = rs.getBytes(columnName);
        return toMultiLineString(bytes);
    }

    @Override
    public MultiLineString getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        byte[] bytes = rs.getBytes(columnIndex);
        return toMultiLineString(bytes);
    }

    @Override
    public MultiLineString getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        byte[] bytes = cs.getBytes(columnIndex);
        return toMultiLineString(bytes);
    }

    /**
     * 解析 MySQL 带 SRID 的 WKB，跳过前4字节后转换为 MultiLineString
     */
    private MultiLineString toMultiLineString(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        try {
            // MySQL Geometry 字段前4字节是SRID，跳过这4字节再解析
            final int SRID_LENGTH = 4;
            if (bytes.length <= SRID_LENGTH) {
                throw new RuntimeException("WKB数据长度不足，无法跳过SRID");
            }
            byte[] wkbWithoutSrid = new byte[bytes.length - SRID_LENGTH];
            System.arraycopy(bytes, SRID_LENGTH, wkbWithoutSrid, 0, wkbWithoutSrid.length);

            WKBReader reader = new WKBReader();
            Geometry geometry = reader.read(wkbWithoutSrid);

            System.out.println("读取到的 Geometry 类型: " + geometry.getGeometryType());
            System.out.println("读取到的 Geometry WKT: " + geometry.toText());

            if (!(geometry instanceof MultiLineString)) {
                throw new RuntimeException("解析结果不是 MultiLineString 类型，实际为: " + geometry.getGeometryType());
            }

            return (MultiLineString) geometry;

        } catch (ParseException e) {
            throw new RuntimeException("无法解析为 MultiLineString", e);
        }
    }
}
